<template>
    <div class="bc-input" :class="{
        'bc-input--suffix': icon||suffix,
        'bc-input--prefix': prefix,
        'bc-input--error': error
        }" :style="{'width': width+'px'}"
        @mouseenter="hovering = true"
        @mouseleave="hovering = false">
        <template v-if="type!=='textarea'">
            <span v-if="prefix" class="bc-input__prefix">
                <bcIcon :name='prefixIcon'
                :color="realIconColor"/>
            </span>
            <input class="bc-input__inner" ref="input"
                :type="type" :value="value" v-bind="$attrs"
                :autofocus="autofocus" :disabled="disabled"
                :readonly="readonly" :placeholder="placeholder"
                :class="{'bc-input--disabled': disabled}"
                @input="$emit('input', $event.target.value)"
                @blur="handleBlur($event.target.value)"
                @focus="handleFocus($event.target.value)"
                @change="$emit('change', $event.target.value)"/>
            <!-- 图标按钮 -->
            <span v-if="icon&&!showClear" class="bc-input__suffix">
                <bcIcon :name='icon' :color="realIconColor"/>
            </span>
            <span v-if="suffix&&!showClear" class="bc-input__suffix">
                <slot name="suffix"></slot>
            </span>
            <span v-if="showClear" @click.stop="clickClear"
                class="bc-input__suffix bc-input--close">
                <bcIcon name='bc-close'
                :color="realIconColor"/>
            </span>
        </template>
        <template v-else>
            <textarea class="bc-textarea__inner" ref="textarea" :value="value" v-bind="$attrs"
                :autofocus="autofocus" :disabled="disabled"
                :readonly="readonly" :placeholder="placeholder"
                :class="{'bc-input--disabled': disabled}"
                :style="{
                    'width': rows,
                    'height': cols,
                    ...textareaCalcStyle
                }"
                @input="$emit('input', $event.target.value)"
                @blur="handleBlur($event.target.value)"
                @focus="handleFocus($event.target.value)"
                @change="$emit('change', $event.target.value)"
            ></textarea>
        </template>
    </div>
</template>

<script>
import BcIcon from "@/components/icon/src/icon.vue";

export default {
    components: { BcIcon },
    name: 'BcInput',
    inheritAttrs:false,
    props: {
        value: [String, Number],
        placeholder: {
            type: [String, Number],
            default: '请输入内容'
        },
        type: {
            type: String,
            default: 'text'
        },
        width: {
            type: Number,
            default: 200
        },
        disabled: Boolean,
        autofocus: Boolean,
        readonly: Boolean,
        prefix: Boolean,
        error: Boolean,
        clear: Boolean,
        icon: String,
        suffix: Boolean,
        prefixIcon: String,
        realIconColor: String,
        rows: String,
        cols: String,
        autosize: [Boolean, Object]
    },
    data() {
        return {
            focus: false,   // 监听输入框的聚焦失焦
            hovering: false,
            textareaCalcStyle: {},
            CONTEXT_STYLE: [
                "width",
                "font-size",
                "box-sizing",
                "line-height",
                "padding-top",
                "font-family",
                "font-weight",
                "text-indent",
                "border-width",
                "padding-left",
                "padding-right",
                "letter-spacing",
                "padding-bottom",
                "text-rendering",
                "text-transform"
            ],
            HIDDEN_STYLE : `
                height:0 !important;
                visibility:hidden !important;
                overflow:hidden !important;
                position:absolute !important;
                z-index:-1000 !important;
                top:0 !important;
                right:0 !important`
        }
    },
    watch: {
        value() {
            this.$nextTick(this.resizeTextarea);
        }
    },
    computed: {
        showClear() {
            if (this.clear&&
                Boolean(this.value)&&
                !this.disabled&&
                (!this.readonly || this.suffix)&&
                (this.hovering||this.focus)
            ) {
                return true
            }
            return false;
        }
    },
    methods: {
        handleBlur(value) {
            this.focus = false;
            this.$emit("blur", value);
        },
        handleFocus(value) {
            // this.$refs.input.focus();
            this.focus=true;
            this.$emit('focus', value);
        },
        clickClear() {
            this.$emit('input', '');
            this.$emit('change', '');
        },
        resizeTextarea() {
            const {autosize, type} = this;
            if (type !== 'textarea' || !autosize) return;
            const minRows = autosize.minRows;
            const maxRows = autosize.maxRows;
            this.textareaCalcStyle = this.calcTextareaHeight(this.$refs.textarea, minRows, maxRows);
        },
        calcTextareaHeight(el, minRows=1, maxRows=null) {
            if (!window.hiddenTextarea) {
                window.hiddenTextarea = document.createElement("textarea");
                document.body.appendChild(window.hiddenTextarea);
            }
            let [boxSizing, paddingSize, borderSize] = this.calculateNodeStyling(el);
            let height = window.hiddenTextarea.scrollHeight;

            if (boxSizing === 'border-box') {
                height = height + borderSize;
            } else if (boxSizing === 'content-box') {
                height = height - paddingSize;
            }

            window.hiddenTextarea.value = '';
            let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;

            if (minRows !== null) {
                let minHeight = singleRowHeight * minRows;
                if (boxSizing === 'border-box') {
                    minHeight = minHeight + paddingSize + borderSize;
                }
                height = Math.max(minHeight, height);
            }
            if (maxRows !== null) {
                let maxHeight = singleRowHeight * maxRows;
                if (boxSizing === 'border-box') {
                    maxHeight = maxHeight + paddingSize + borderSize;
                }
                height = Math.min(maxHeight, height);
            }
            window.hiddenTextarea.parentNode &&
                window.hiddenTextarea.parentNode.removeChild(window.hiddenTextarea);
            window.hiddenTextarea = null;

            return { height: height + 'px' };
        },
        calculateNodeStyling(el) {
            window.hiddenTextarea.value = this.value;
            const style = window.getComputedStyle(el);
            const boxSizing = style.getPropertyValue('box-sizing');
            const paddingTop = style.getPropertyValue("padding-top");
            const paddingBottom = style.getPropertyValue("padding-bottom");
            const borderTopWidth = style.getPropertyValue("border-top-width");
            const borderBottomWidth = style.getPropertyValue("border-bottom-width");
            const contextStyle = this.CONTEXT_STYLE.map(
                name => `${name}:${style.getPropertyValue(name)}`
            ).join(";");
            window.hiddenTextarea.setAttribute(
                "style",
                `${contextStyle};${this.HIDDEN_STYLE}`
            );
            return [
                boxSizing,
                parseInt(paddingBottom) + parseInt(paddingTop),
                parseInt(borderBottomWidth) + parseInt(borderTopWidth)
            ];
        }
    },
    mounted() {
        this.$nextTick(this.resizeTextarea);
    }
}
</script>

<style scoped>
.bc-input {
    position: relative;
    display: inline-block;
    font-size: 14px;
}
.bc-input.bc-input--suffix>.bc-input__inner {
    padding-right: 30px;
}
.bc-input.bc-input--prefix>.bc-input__inner {
    padding-left: 30px;
}
.bc-input>.bc-input__inner {
    display: inline-block;
    width: 100%;
    height: 36px;
    line-height: 36px;
    padding: 0 15px;
    outline: none;
    font-size: inherit;
    background-color: #fff;
    border: 1px solid #000;
    border-radius: 4px;
    cursor: pointer;
}
.bc-input>.bc-input__inner:focus {
    border: 1px solid #2d8cf0;
}
.bc-input>.bc-textarea__inner {
    display: block;
    width: 100%;
    height: 36px;
    line-height: 1.5;
    padding: 5px 15px;
    font-size: inherit;
    outline: none;
    background-color: #fff;
    border: 1px solid #000;
    border-radius: 4px;
    box-sizing: border-box;
}
.bc-input>.bc-textarea__inner:focus {
    border: 1px solid #2d8cf0;
}
.bc-input>.bc-input__suffix {
    position: absolute;
    display: flex;
    top: 0;
    right: 0;
    width: 30px;
    height: 100%;
    justify-content: center;
    align-items: center;
}
.bc-input>.bc-input__prefix {
    position: absolute;
    display: flex;
    top: 0;
    left: 0;
    width: 30px;
    height: 100%;
    justify-content: center;
    align-items: center;
}
.bc-input>.bc-input--close {
    transition: transform 0.5s;
}
.bc-input>.bc-input--close:hover {
    transform: rotateZ(180deg);
}
</style>